package com.lanchetech.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaSecCheckService;
import com.alibaba.excel.util.StringUtils;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.lanchetech.bean.request.*;
import com.lanchetech.bean.response.BasePageResp;
import com.lanchetech.bean.response.BaseResp;
import com.lanchetech.bean.response.ResultData;
import com.lanchetech.bean.util.PageHelpUtil;
import com.lanchetech.bean.vo.*;
import com.lanchetech.common.enums.*;
import com.lanchetech.dao.*;
import com.lanchetech.entity.*;
import com.lanchetech.service.DaoService;
import com.lanchetech.service.OSSClientUtil;
import com.lanchetech.user.service.BlogService;
import com.lanchetech.user.service.MiniappService;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.lanchetech.common.constants.JypConstant.MAX_READ_COUNT;

@Service
public class BlogServiceImpl implements BlogService {

    @Autowired
    BlogMapper blogMapper;

    @Autowired
    UserMapper userMapper;

    @Autowired
    DaoService daoService;

    @Autowired
    BlogSpuMapper blogSpuMapper;

    @Autowired
    SpuMapper spuMapper;

    @Autowired
    BlogGoodsMapper blogGoodsMapper;

    @Autowired
    TagCategoryMapper tagCategoryMapper;

    @Autowired
    BlogCollectMapper blogCollectMapper;

    @Autowired
    UserInfoMapper userInfoMapper;

    @Autowired
    CommonCommentMapper commonCommentMapper;

    @Autowired
    CommonCommentGoodsMapper commonCommentGoodsMapper;

    @Autowired
    AnchorAttentionMapper anchorAttentionMapper;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    UserTagMapper userTagMapper;

    @Autowired
    OSSClientUtil ossClientUtil;

    @Autowired
    MiniappService miniappService;

    @Override
    public ResultData<BasePageResp<BlogVO>> getBlogPage(BlogPageReq req, User user) {
        if (user != null && user.getId().equals(req.getUserId())) {
            return getMyBlogPage(req);
        }
        //计算tfidf
        if (req.getTitle() != null && user != null) {
            tfidfMethod(req.getTitle(), UserTagTypeEnum.BLOG.getType());
        }

        req.setStatus(BlogAuditStatusEnum.PASS.getAuditStatus());
        return getBlogPageCommon(req, user);
    }

    private ResultData<BasePageResp<BlogVO>> getBlogPageCommon(BlogPageReq req, User user) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<BlogVO> list = blogMapper.findAllPage(req);
        if (!CollectionUtils.isEmpty(list)) {
            List<BlogSpu> blogSpus = blogSpuMapper.findByBlogIds(list.stream().map(BlogVO::getId).collect(Collectors.toList()));
            List<Long> spuIds = blogSpus.stream().map(BlogSpu::getSpuId).collect(Collectors.toList());
            Map<Long, List<Spu>> blogSpuMap = new HashMap<>();
            if (!CollectionUtils.isEmpty(spuIds)) {
                Map<Long, Spu> spuMap = daoService.getSpuMap(spuIds);
                if (!CollectionUtils.isEmpty(blogSpus)) {
                    blogSpus.stream().forEach(item -> {
                        if (!blogSpuMap.containsKey(item.getBlogId())) {
                            List<Spu> spuList = new ArrayList<>();
                            spuList.add(spuMap.get(item.getSpuId()));
                            blogSpuMap.put(item.getBlogId(), spuList);
                        } else {
                            List<Spu> spuList = blogSpuMap.get(item.getBlogId());
                            spuList.add(spuMap.get(item.getSpuId()));
                            blogSpuMap.put(item.getBlogId(), spuList);
                        }
                    });
                }
            }

            Map<Long, BlogCollect> blogCollectMap = new HashMap<>();
            if (user != null) {
                List<BlogCollect> blogCollects = blogCollectMapper.findAllByUserId(user.getId());
                if (!CollectionUtils.isEmpty(blogCollects)) {
                    blogCollects.stream().forEach(item -> {
                        blogCollectMap.put(item.getBlogId(), item);
                    });
                }
            }


            Map<Long, AnchorAttention> anchorAttentionMap = new HashMap<>();
            if (user != null) {
                List<AnchorAttention> anchorAttentionList = anchorAttentionMapper.findAllByUserId(user.getId());
                if (!CollectionUtils.isEmpty(anchorAttentionList)) {
                    anchorAttentionList.stream().forEach(item -> {
                        anchorAttentionMap.put(item.getAnchorUserId(), item);
                    });
                }
            }

            Map<Long, User> userMap = daoService.getUserMap(list.stream().map(BlogVO::getUserId).collect(Collectors.toList()));
            Map<Long, BlogGoods> blogGoodsMap = new HashMap<>();
            if (user != null) {
                List<BlogGoods> blogGoods = blogGoodsMapper.findAllByUserId(user.getId());
                if (!CollectionUtils.isEmpty(blogGoods)) {
                    blogGoods.stream().forEach(item -> {
                        blogGoodsMap.put(item.getBlogId(), item);
                    });
                }
            }

            List<CommentNumVO> commentNums = commonCommentMapper.findCommentNum(list.stream().map(BlogVO::getId).collect(Collectors.toList()));
            Map<Long, Long> commonNumMap = new HashMap<>();
            if (!CollectionUtils.isEmpty(commentNums)) {
                commentNums.stream().forEach(item -> {
                    commonNumMap.put(item.getBlogId(), item.getNum());
                });
            }

            List<CommentNumVO> blogCollectList = blogCollectMapper.findCollectNum(list.stream().map(BlogVO::getId).collect(Collectors.toList()));
            Map<Long, Long> blogCollectNumMap = new HashMap<>();
            if (!CollectionUtils.isEmpty(blogCollectList)) {
                blogCollectList.stream().forEach(item -> {
                    blogCollectNumMap.put(item.getBlogId(), item.getNum());
                });
            }

            List<Long> tagCategoryIds = list.stream().map(BlogVO::getFirstTagId).collect(Collectors.toList());
            tagCategoryIds.addAll(list.stream().map(BlogVO::getSecondTagId).collect(Collectors.toList()));
            Map<Long, TagCategory> categoryMap = daoService.getTagCategoryMap(tagCategoryIds);

            list.stream().forEach(item -> {
                item.setFirstTagTitle(categoryMap.get(item.getFirstTagId()) != null ? categoryMap.get(item.getFirstTagId()).getTitle() : null);
                item.setSecondTagTitle(categoryMap.get(item.getSecondTagId()) != null ? categoryMap.get(item.getSecondTagId()).getTitle() : null);
                item.setNickname(userMap.get(item.getUserId()).getNickname());
                item.setAvatar(userMap.get(item.getUserId()).getAvatar());
                item.setIsGood(blogGoodsMap.containsKey(item.getId()));
                item.setCommentNum(commonNumMap.get(item.getId()));
                item.setSpuList(blogSpuMap.get(item.getId()));
                item.setIsCollect(blogCollectMap.containsKey(item.getId()));
                item.setIsAttention(anchorAttentionMap.containsKey(item.getUserId()));
                item.setCollectNum(blogCollectNumMap.get(item.getId()));
            });
        }
        return PageHelpUtil.buildPage(list, page);
    }

    private void tfidfMethod(String search, Byte type) {
        ValueOperations<String, List<TagSpuStatisticsVO>> operations = redisTemplate.opsForValue();
        if (operations.get("tfidf" + type) != null) {
            tfidfUtil(operations.get("tfidf" + type), search, type);
        } else {
            //标题总字数
            List<StatisticsCountVO> totalWordCounts = blogMapper.getTotalWordCount();
            Map<Long, Long> totalWordCountMap = new HashMap<>();
            if (!CollectionUtils.isEmpty(totalWordCounts)) {
                totalWordCounts.stream().forEach(item -> {
                    totalWordCountMap.put(item.getId(), item.getCount());
                });
            }

            //博文总数
            List<StatisticsCountVO> itemCount = blogMapper.getItemCount();
            Map<Long, Long> itemCountMap = new HashMap<>();
            if (!CollectionUtils.isEmpty(itemCount)) {
                itemCount.stream().forEach(item -> {
                    itemCountMap.put(item.getId(), item.getCount());
                });
            }

            //计算统计数量
            List<TagSpuStatisticsVO> voList = new ArrayList<>();
            totalWordCounts.stream().forEach(item -> {
                TagSpuStatisticsVO vo = new TagSpuStatisticsVO();
                vo.setType(type);
                vo.setRelateId(item.getId());
                vo.setItemCount(itemCountMap.get(item.getId()));
                vo.setUpdateAt(new Date());
                vo.setTotalWordCount(totalWordCountMap.get(item.getId()));
                voList.add(vo);
            });
            operations.set("tfidf" + type, voList);

            tfidfUtil(voList, search, type);
        }
    }

    private void tfidfUtil(List<TagSpuStatisticsVO> list, String search, Byte type) {
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        ValueOperations<String, List<SearchTfidfVO>> operations = redisTemplate.opsForValue();
        List<SearchTfidfVO> searchTfidfVOS = new ArrayList<>();
        List<SearchTfidfVO> newSearchTfidfVO = new ArrayList<>();
        if (operations.get("tfidf" + search + type) != null) {
            searchTfidfVOS.addAll(operations.get("tfidf" + search + type));
        }

        Boolean isUseful = false;
        if (!CollectionUtils.isEmpty(searchTfidfVOS)) {
            isUseful = true;
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).getUpdateAt().after(searchTfidfVOS.get(0).getSearchTime())) {
                    isUseful = false;
                }
            }
        }
        if (!CollectionUtils.isEmpty(searchTfidfVOS) && isUseful) {
            //是否被其他用户查询过 且商品或博文没有变更
            Collections.sort(searchTfidfVOS, (o1, o2) -> o2.getTfidf().compareTo(o1.getTfidf()));
            newSearchTfidfVO.addAll(searchTfidfVOS);
        } else {
            Map<Long, TagCategory> tagCategoryMap = daoService.getTagCategoryMap(list.stream().map(TagSpuStatisticsVO::getRelateId).collect(Collectors.toList()));
            if (!CollectionUtils.isEmpty(list)) {
                //出现博文数量
                List<StatisticsCountVO> itemHaveCounts = blogMapper.countLikeSearch(search);
                Map<Long, Long> itemHaveCountMap = new HashMap<>();
                if (!CollectionUtils.isEmpty(itemHaveCounts)) {
                    itemHaveCounts.stream().forEach(item -> {
                        itemHaveCountMap.put(item.getId(), item.getCount());
                    });
                }

                //查询关键词出现次数
                List<StatisticsCountVO> displayCounts = blogMapper.getDisplayCount(search);
                Map<Long, Long> displayCountsMap = new HashMap<>();
                if (!CollectionUtils.isEmpty(displayCounts)) {
                    displayCounts.stream().forEach(item -> {
                        displayCountsMap.put(item.getId(), item.getCount());
                    });
                }

                //计算tfidf并保存
                list.stream().forEach(item -> {
                    Long displayCount = displayCountsMap.get(item.getRelateId()) != null ? displayCountsMap.get(item.getRelateId()) : 0L;
                    Long itemHaveCount = itemHaveCountMap.get(item.getRelateId()) != null ? itemHaveCountMap.get(item.getRelateId()) : 0L;
                    newSearchTfidfVO.add(SearchTfidfVO.builder()
                            .search(search)
                            .type(type)
                            .displayCount(displayCount)
                            .itemHaveCount(itemHaveCount)
                            .tagName(tagCategoryMap.get(item.getRelateId()) != null ? tagCategoryMap.get(item.getRelateId()).getTitle() : null)
                            .relateId(item.getRelateId())
                            .tfidf((Double.valueOf(displayCount) / item.getTotalWordCount()) * (Math.log(Double.valueOf(item.getItemCount()) / (itemHaveCount + 1))))
                            .searchTime(new Date())
                            .build());
                });
            }
            operations.set("tfidf" + search + type, newSearchTfidfVO);

            Collections.sort(newSearchTfidfVO, (o1, o2) -> o2.getTfidf().compareTo(o1.getTfidf()));
        }

        //存在标签更新 不存在新建
        List<UserTag> existUserTags = userTagMapper.findAllByUserIdAndType(user.getId(), UserTagTypeEnum.BLOG.getType());
        Map<Long, UserTag> existMap = new HashMap<>();
        existUserTags.stream().forEach(item -> {
            existMap.put(item.getRelateId(), item);
        });
        List<UserTag> userTags = new ArrayList<>();
        List<UserTag> updateUserTag = new ArrayList<>();
        for (int i = 0; i < newSearchTfidfVO.size() && i < 2; i++) {
            if (existMap.containsKey(newSearchTfidfVO.get(i).getRelateId())) {
                UserTag userTag = existMap.get(newSearchTfidfVO.get(i).getRelateId());
                userTag.setWeight(userTag.getWeight() + 2 - i);
                updateUserTag.add(userTag);
            } else {
                userTags.add(UserTag.builder()
                        .userId(user.getId())
                        .type(type)
                        .weight(2 - i)
                        .relateId(newSearchTfidfVO.get(i).getRelateId())
                        .tagName(newSearchTfidfVO.get(i).getTagName())
                        .search(search)
                        .build());
            }

        }
        if (!CollectionUtils.isEmpty(updateUserTag)) {
            userTagMapper.updateBatchWeight(updateUserTag);
        }
        if (!CollectionUtils.isEmpty(userTags)) {
            userTagMapper.batchInsert(userTags);
        }

    }

    @Override
    public ResultData<BasePageResp<BlogVO>> getMyBlogPage(BlogPageReq req) {
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        req.setUserId(user.getId());
        return getBlogPageCommon(req, user);
    }

    @Override
    public ResultData<BasePageResp<BlogVO>> getGoodsBlogPage(BlogGoodsPageReq req) {
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if (req.getUserId() == null) {
            req.setUserId(user.getId());
        }
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<BlogGoods> list = blogGoodsMapper.findAllPage(req);
        List<BlogVO> vos = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            Map<Long, Blog> blogMap = daoService.getBlogMap(list.stream().map(BlogGoods::getBlogId).collect(Collectors.toList()));
            if (!CollectionUtils.isEmpty(list)) {
                Map<Long, User> userMap = daoService.getUserMap(blogMap.values().stream().map(Blog::getUserId).collect(Collectors.toList()));
                List<BlogGoods> blogGoods = blogGoodsMapper.findAllByUserId(user.getId());
                Map<Long, BlogGoods> blogGoodsMap = new HashMap<>();
                if (!CollectionUtils.isEmpty(blogGoods)) {
                    blogGoods.stream().forEach(item -> {
                        blogGoodsMap.put(item.getBlogId(), item);
                    });
                }

                list.stream().forEach(item -> {
                    BlogVO vo = new BlogVO();
                    Blog blogItem = blogMap.get(item.getBlogId());
                    if (blogItem != null) {
                        BeanUtils.copyProperties(blogItem, vo);
                        vo.setNickname(userMap.get(blogMap.get(item.getBlogId()).getUserId()).getNickname());
                        vo.setAvatar(userMap.get(blogMap.get(item.getBlogId()).getUserId()).getAvatar());
                        vo.setIsGood(blogGoodsMap.containsKey(item.getId()));
                    }
                    vos.add(vo);
                });
            }
        }
        return PageHelpUtil.buildPage(vos, page);
    }

    @Override
    public ResultData<BasePageResp<BlogVO>> getCollectBlogPage(BlogCollectPageReq req) {
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if (req.getUserId() == null) {
            req.setUserId(user.getId());
        }
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<BlogVO> vos = new ArrayList<>();
        List<BlogCollect> list = blogCollectMapper.findAllPage(req);
        if (!CollectionUtils.isEmpty(list)) {
            Map<Long, Blog> blogMap = daoService.getBlogMap(list.stream().map(BlogCollect::getBlogId).collect(Collectors.toList()));
            if (!CollectionUtils.isEmpty(list)) {
                Map<Long, User> userMap = daoService.getUserMap(blogMap.values().stream().map(Blog::getUserId).collect(Collectors.toList()));
                List<BlogGoods> blogGoods = blogGoodsMapper.findAllByUserId(user.getId());
                Map<Long, BlogGoods> blogGoodsMap = new HashMap<>();
                if (!CollectionUtils.isEmpty(blogGoods)) {
                    blogGoods.stream().forEach(item -> {
                        blogGoodsMap.put(item.getBlogId(), item);
                    });
                }

                list.stream().forEach(item -> {
                    BlogVO vo = new BlogVO();
                    Blog blogItem = blogMap.get(item.getBlogId());
                    if (blogItem != null) {
                        BeanUtils.copyProperties(blogItem, vo);
                        vo.setNickname(userMap.get(blogMap.get(item.getBlogId()).getUserId()).getNickname());
                        vo.setAvatar(userMap.get(blogMap.get(item.getBlogId()).getUserId()).getAvatar());
                        vo.setIsGood(blogGoodsMap.containsKey(item.getId()));
                    }
                    vos.add(vo);
                });
            }
        }
        return PageHelpUtil.buildPage(vos, page);
    }

    @Override
    public ResultData<BlogDetailVO> getBlogDetail(Long id) {
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        BlogDetailVO vo = new BlogDetailVO();
        Blog blog = blogMapper.selectByPrimaryKey(id);
        TagCategory firstTag = tagCategoryMapper.selectByPrimaryKey(blog.getFirstTagId());
        TagCategory secondTag = tagCategoryMapper.selectByPrimaryKey(blog.getSecondTagId());
        if ((BlogAuditStatusEnum.PASS.getAuditStatus().equals(blog.getAuditStatus()) || blog.getUserId().equals(user.getId())) && DeletedEnum.DEFAULT.getStatus().equals(blog.getDeleted())){
            BeanUtils.copyProperties(blog, vo);
            User blogUser = userMapper.selectByPrimaryKey(blog.getUserId());
            vo.setNickname(blogUser.getNickname());
            vo.setAvatar(blogUser.getAvatar());
            List<BlogSpu> blogSpus = blogSpuMapper.findAllByBlogId(id);
            List<Long> spuIds = blogSpus.stream().map(BlogSpu::getSpuId).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(spuIds)) {
                vo.setSpuList(spuMapper.findAllByIds(spuIds));
            }
            vo.setIsAttention(anchorAttentionMapper.findOneByUserIdAndAnchorUserId(user.getId(), blog.getUserId()) != null);
            vo.setFirstTagTitle(firstTag != null ? firstTag.getTitle() : null);
            vo.setSecondTagTitle(secondTag != null ? secondTag.getTitle() : null);
            vo.setIsGood(blogGoodsMapper.findOneByBlogIdAndUserId(id, user.getId()) != null);
            vo.setCollectNum(blogCollectMapper.countByBlogId(id));
            vo.setCommentNum(commonCommentMapper.countByRelateId(id));
            vo.setIsCollect(blogCollectMapper.findOneByBlogIdAndUserId(id, user.getId()) != null);
        }


        if(firstTag != null) {
            //是否被贴过标签
            List<UserTag> userTags = userTagMapper.findAllByUserIdAndType(user.getId(), UserTagTypeEnum.BLOG.getType());
            if (CollectionUtils.isEmpty(userTags)) {
                ValueOperations<String, Integer> operations = redisTemplate.opsForValue();
                Integer readCount = operations.get(UserTagTypeEnum.BLOG.getType().toString() + blog.getFirstTagId().toString());
                if (readCount == null) {
                    operations.set(UserTagTypeEnum.BLOG.getType().toString() + blog.getFirstTagId().toString(), 1, 24, TimeUnit.HOURS);
                } else {
                    readCount++;
                    if (readCount >= MAX_READ_COUNT) {
                        userTagMapper.insert(UserTag.builder()
                                .userId(user.getId())
                                .type(UserTagTypeEnum.BLOG.getType())
                                .weight(1)
                                .relateId(blog.getFirstTagId())
                                .tagName(firstTag.getTitle())
                                .build());
                    } else {
                        operations.set(UserTagTypeEnum.BLOG.getType().toString() + blog.getFirstTagId().toString(), readCount, 24, TimeUnit.HOURS);
                    }
                }
            }
        }

        return new ResultData<>(vo);
    }

    @Override
    public ResultData<BlogDetailVO> getBlogDraft(User user) {
        Blog draft = blogMapper.findOneByUserIdAndAuditStatus(user.getId(), BlogAuditStatusEnum.SAVE_DRAFT.getAuditStatus());
        return draft != null ? getBlogDetail(draft.getId()) : new ResultData<>(null);
    }

    @Override
    public BaseResp editBlogGoods(Long id) {
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        BlogGoods blogGoods = blogGoodsMapper.findOneByBlogIdAndUserId(id, user.getId());
        Blog blog = blogMapper.selectByPrimaryKey(id);
        if (!BlogAuditStatusEnum.PASS.getAuditStatus().equals(blog.getAuditStatus()) || DeletedEnum.DELETED.getStatus().equals(blog.getDeleted())) {
            return new BaseResp(ResultCode.BLOG_NOT_FIND);
        }
        if (blogGoods == null) {
            blogGoodsMapper.insert(BlogGoods.builder()
                    .userId(user.getId())
                    .blogId(id)
                    .title(blog.getTitle())
                    .createdAt(new Date())
                    .build());
            blogMapper.addGoods(id);
        } else {
            blogGoodsMapper.deleteByUserIdAndBlogId(user.getId(), id);
            blogMapper.reduceGoods(id);
        }
        return new BaseResp();
    }

    @Override
    public BaseResp editBlogCollect(Long id) {
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        BlogCollect blogCollect = blogCollectMapper.findOneByBlogIdAndUserId(id, user.getId());
        Blog blog = blogMapper.selectByPrimaryKey(id);
        UserInfo userInfo = userInfoMapper.findOneByUserId(user.getId());
        if (!BlogAuditStatusEnum.PASS.getAuditStatus().equals(blog.getAuditStatus()) || DeletedEnum.DELETED.getStatus().equals(blog.getDeleted())) {
            return new BaseResp(ResultCode.BLOG_NOT_FIND);
        }

        if (blogCollect == null) {
            blogCollectMapper.insert(BlogCollect.builder()
                    .userId(user.getId())
                    .blogId(id)
                    .title(blog.getTitle())
                    .createdAt(new Date())
                    .build());

            userInfoMapper.updateAttentionCountById(userInfo.getAttentionCount() + 1, userInfo.getId());
        } else {
            blogCollectMapper.deleteByUserIdAndBlogId(user.getId(), id);

            userInfoMapper.updateAttentionCountById(userInfo.getAttentionCount() - 1, userInfo.getId());
        }
        return new BaseResp();
    }

    private String buildImage(String video) {
        try {
            return ossClientUtil.uploadWebImageOriginally(video + "?x-oss-process=video/snapshot,t_1000,f_png,w_0,h_0,m_fast");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public BaseResp editBlog(BlogReq req) {
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if (req.getId() == null) {
            if (BlogAuditStatusEnum.WAIT_AUDIT.getAuditStatus().equals(req.getAuditStatus()) || BlogAuditStatusEnum.SAVE_DRAFT.getAuditStatus().equals(req.getAuditStatus())) {

                // 如果是视频类型并且没有封面，则主动生成一张封面
                if (BlogTypeEnum.VIDEO.getType().equals(req.getType()) && req.getCoverImage() == null) {
                    req.setCoverImage(buildImage(req.getVideo()));
                }

                req.setUserId(user.getId());
                req.setGoods(0L);
                req.setAuditStatus(req.getAuditStatus());
                req.setDeleted(DeletedEnum.DEFAULT.getStatus());
                req.setCreatedAt(new Date());
                req.setUpdatedAt(new Date());
                req.setTenantId(req.getTenantId() == null ? 0L : user.getShopId() == null ? 0L : user.getShopId());
                blogMapper.insert(req);

                List<Long> spuIds = req.getSpuIds();
                List<BlogSpu> blogSpus = new ArrayList<>();
                if (!CollectionUtils.isEmpty(spuIds)) {
                    spuIds.stream().forEach(item -> {
                        blogSpus.add(BlogSpu.builder()
                                .userId(user.getId())
                                .blogId(req.getId())
                                .spuId(item)
                                .createdAt(new Date())
                                .updatedAt(new Date())
                                .build());
                    });
                    blogSpuMapper.batchInsert(blogSpus);
                }

                tagCategoryMapper.updateHotsbyid(1, req.getSecondTagId());
            }
        } else {
            req.setUserId(user.getId());
            req.setGoods(0L);
            if (BlogAuditStatusEnum.WAIT_AUDIT.getAuditStatus().equals(req.getAuditStatus()) || BlogAuditStatusEnum.SAVE_DRAFT.getAuditStatus().equals(req.getAuditStatus())) {
                req.setAuditStatus(req.getAuditStatus());
            } else {
                req.setAuditStatus(BlogAuditStatusEnum.WAIT_AUDIT.getAuditStatus());
            }
            req.setUpdatedAt(new Date());
            req.setTenantId(req.getTenantId() == null ? 0L : user.getShopId() == null ? 0L : user.getShopId());
            blogMapper.updateByPrimaryKeySelective(req);

            List<Long> spuIds = req.getSpuIds();
            List<BlogSpu> blogSpus = new ArrayList<>();
            if (!CollectionUtils.isEmpty(spuIds)) {
                blogSpuMapper.deleteByBlogId(req.getId());
                spuIds.stream().forEach(item -> {
                    blogSpus.add(BlogSpu.builder()
                            .userId(user.getId())
                            .blogId(req.getId())
                            .spuId(item)
                            .createdAt(new Date())
                            .updatedAt(new Date())
                            .build());
                });
                blogSpuMapper.batchInsert(blogSpus);
            }
        }
        return new BaseResp();
    }

    private void saveEditStatistics(Blog blog, Long firstTagId) {
        //添加删除或修改了商品名称就重新统计数据
        ValueOperations<String, List<TagSpuStatisticsVO>> operations = redisTemplate.opsForValue();
        if (blog == null || blog.getTitle() != null) {

            //标题总字数
            StatisticsCountVO totalWordCounts = blogMapper.getTotalWordCountByFirstTagId(firstTagId);

            //博文总数
            StatisticsCountVO itemCount = blogMapper.getItemCountByFirstTagId(firstTagId);

            TagSpuStatisticsVO vo = new TagSpuStatisticsVO();
            vo.setType(UserTagTypeEnum.BLOG.getType());
            vo.setRelateId(firstTagId);
            vo.setItemCount(itemCount.getCount());
            vo.setUpdateAt(new Date());
            vo.setTotalWordCount(totalWordCounts.getCount());

            if (operations.get("tfidf" + UserTagTypeEnum.BLOG.getType()) != null) {
                //更新其中一条
                List<TagSpuStatisticsVO> statisticsVO = operations.get("tfidf" + UserTagTypeEnum.BLOG.getType());
                List<TagSpuStatisticsVO> addStatistics = new ArrayList<>();
                statisticsVO.stream().forEach(item -> {
                    if (item.getRelateId().equals(firstTagId)) {
                        BeanUtils.copyProperties(vo, item);
                    } else {
                        addStatistics.add(vo);
                    }
                });
                if (!CollectionUtils.isEmpty(addStatistics)) {
                    statisticsVO.addAll(addStatistics);
                }
                operations.set("tfidf" + UserTagTypeEnum.BLOG.getType(), statisticsVO);
            }
        }
    }


    @Override
    public BaseResp deleteBlog(Long id) {
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Blog blog = blogMapper.selectByPrimaryKey(id);
        if (user.getId().equals(blog.getUserId())) {
            blogMapper.updateDeletedById(DeletedEnum.DELETED.getStatus(), id);
        }

        //重新统计并保存数据
        if(blog.getFirstTagId() != null && blog.getFirstTagId() != 0){
            saveEditStatistics(null, blog.getFirstTagId());
        }

        return new BaseResp();
    }

    @Override
    public ResultData<List<TagCategory>> getTagCategoryList(Long pid) {
        List<TagCategory> tagCategories = tagCategoryMapper.findAllByPid(pid);
        return new ResultData<>(tagCategories);
    }

    @Override
    public ResultData<List<TagCategory>> getAllTagCategoryList() {
        List<TagCategory> tagCategories = tagCategoryMapper.findAll();
        return new ResultData<>(tagCategories);
    }

    @Override
    public ResultData<Long> editCommonComment(CommonComment req) {
        Long result = 0L;
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if (req.getId() == null) {
            ResultData<Long> resultData = new ResultData<>();
            WxMaSecCheckService wxMaSecCheckService = miniappService.wxMaSecCheckService();
            try {
                if(!StringUtils.isEmpty(req.getContent())){
                    if(!wxMaSecCheckService.checkMessage(req.getContent())){
                        resultData.setResultCode(ResultCode.COMMENT_CONTENT_ERROR);
                        return resultData;
                    }
                }
            } catch (WxErrorException e) {
                resultData.setResultCode(ResultCode.COMMENT_CONTENT_ERROR);
                return resultData;
            }

            req.setUserId(user.getId());
            req.setGoodCount(0L);
            req.setCreatedAt(new Date());
            req.setCommentCount(0L);
            commonCommentMapper.insert(req);
            result = req.getId();

            if (!req.getRid().equals(0L)) {
                List<CommonComment> allByRid = commonCommentMapper.findAllByRid(req.getRid());
                if (allByRid.size() == 1) {
                    commonCommentMapper.updateFirstCommentIdById(req.getId(), req.getRid());
                }
                commonCommentMapper.addCommentCount(req.getRid());
            }
        }
        return new ResultData<>(result);
    }

    @Override
    public ResultData<BasePageResp<CommonCommentVO>> getCommonCommentPage(PageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        List<CommonCommentVO> list = commonCommentMapper.findAllPage(req);
        if (!CollectionUtils.isEmpty(list)) {
            List<Long> firstCommentIds = list.stream().map(CommonCommentVO::getFirstCommentId).collect(Collectors.toList());
            List<Long> userIds = list.stream().map(CommonCommentVO::getUserId).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(firstCommentIds)) {
                firstCommentIds.add(0L);
            }
            Map<Long, CommonComment> commonCommentMap = daoService.getCommonCommentMap(firstCommentIds);
            List<CommonCommentGoods> commonCommentGoods = commonCommentGoodsMapper.findAllByUserId(user.getId());
            List<Long> commentIds = commonCommentGoods.stream().map(CommonCommentGoods::getCommentId).collect(Collectors.toList());

            userIds.addAll(commonCommentMap.values().stream().map(CommonComment::getUserId).collect(Collectors.toList()));
            Map<Long, User> userMap = daoService.getUserMap(userIds);
            Map<Long, CommonCommentVO> commonCommentVOMap = new HashMap<>();
            commonCommentMap.values().stream().forEach(item -> {
                CommonCommentVO vo = new CommonCommentVO();
                BeanUtils.copyProperties(item, vo);
                vo.setAvatar(userMap.get(item.getUserId()).getAvatar());
                vo.setUserNickname(userMap.get(item.getUserId()).getNickname());
                vo.setIsGoods(commentIds.contains(item.getId()));
                commonCommentVOMap.put(item.getId(), vo);
            });


            list.stream().forEach(item -> {
                item.setFirstComment(commonCommentVOMap.get(item.getFirstCommentId()));
                item.setUserNickname(userMap.get(item.getUserId()).getNickname());
                item.setAvatar(userMap.get(item.getUserId()).getAvatar());
                item.setIsGoods(commentIds.contains(item.getId()));
            });
        }
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public BaseResp editCommonCommentGoods(Long id) {
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        CommonCommentGoods commonCommentGoods = commonCommentGoodsMapper.findOneByUserIdAndCommentId(user.getId(), id);
        CommonComment commonComment = commonCommentMapper.selectByPrimaryKey(id);
        if (commonCommentGoods == null) {
            commonCommentGoodsMapper.insert(CommonCommentGoods.builder()
                    .userId(user.getId())
                    .commentId(id)
                    .createdAt(new Date())
                    .build());

            commonComment.setGoodCount(commonComment.getGoodCount() + 1);
        } else {
            commonCommentGoodsMapper.deleteByPrimaryKey(commonCommentGoods.getId());
            commonComment.setGoodCount(commonComment.getGoodCount() - 1);
        }
        commonCommentMapper.updateByPrimaryKey(commonComment);
        return new BaseResp();
    }

    @Override
    public BaseResp deleteCommonComment(Long id) {
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        CommonComment commonComment = commonCommentMapper.selectByPrimaryKey(id);
        if (commonComment.getUserId().equals(user.getId())) {
            commonCommentMapper.deleteByPrimaryKey(id);

            if (commonComment.getRid() != 0L) {
                CommonComment mainCommonComment = commonCommentMapper.selectByPrimaryKey(commonComment.getRid());
                //删除了第一条评论
                if (mainCommonComment.getFirstCommentId().equals(mainCommonComment)) {
                    CommonComment commentLastOne = commonCommentMapper.findCommentLastOne(mainCommonComment.getId());
                    commonCommentMapper.updateFirstCommentIdById(commentLastOne.getId(), commonComment.getRid());
                }
            } else {
                commonCommentMapper.deleteByPrimaryKey(id);
            }
        }
        return new BaseResp();
    }
}
